﻿using System;
using System.Collections.Generic;
using System.IO;
using System.IO.Compression;
using System.Linq;
using System.Runtime.Intrinsics.Arm;
using System.Security.Cryptography;
using System.Text;
using System.Text.RegularExpressions;

namespace Common
{
    /// <summary>
    /// FileName: Function.cs
    /// CLRVersion: 4.0.30319.42000
    /// @author zhangsx
    /// @date 2017/04/12 11:18:19
    /// Corporation:
    /// Description:    
    /// </summary> 
    public static class FunctionTools
    {
        /// <summary>
        /// 将二进制转换成字符串 
        /// </summary>
        /// <param name="value"></param>
        /// <returns></returns>
        public static string ConvertToString(this byte[] value)
        {
            return Encoding.Default.GetString(value);
            //return System.BitConverter.ToString(value);
            //return Encoding.UTF8.GetString(value);
        }
        /// <summary>
        /// 将字符串转换成二进制 
        /// </summary>
        /// <param name="value"></param>
        /// <returns></returns>
        public static byte[] ConvertToByte(this string value)
        {
            return Encoding.Default.GetBytes(value);
        }

        /// <summary>
        /// 将二进制转换成UTF-8字符串 
        /// </summary>
        /// <param name="value"></param>
        /// <returns></returns>
        public static string ConvertToUTF8String(this byte[] value)
        {
            return Encoding.UTF8.GetString(value);
        }

        /// <summary>
        /// 将字符串转换成UTF-8二进制
        /// </summary>
        /// <param name="value"></param>
        /// <returns></returns>
        public static byte[] ConvertToUTF8Bytes(this string value)
        {
            return Encoding.UTF8.GetBytes(value);
        }

        /// <summary>
        /// 压缩 
        /// </summary>
        /// <param name="value"></param>
        /// <returns></returns>
        public static byte[] Compress(this byte[] value)
        {
            MemoryStream outStream = new MemoryStream();
            using (MemoryStream intStream = new MemoryStream(value))
            {
                using (GZipStream Compress =
                    new GZipStream(outStream,
                    CompressionMode.Compress))
                {
                    intStream.CopyTo(Compress);
                }
            }
            return outStream.ToArray();
        }

        /// <summary>
        /// 解压缩
        /// </summary>
        /// <param name="value"></param>
        /// <returns></returns>
        public static byte[] Decompress(this byte[] value)
        {
            byte[] result = null;
            MemoryStream compressedStream = new MemoryStream(value);
            using (MemoryStream outStream = new MemoryStream())
            {
                using (GZipStream Decompress = new GZipStream(compressedStream,
                        CompressionMode.Decompress))
                {
                    Decompress.CopyTo(outStream);
                    result = outStream.ToArray();
                }
            }
            return result;
        }

        /// <summary>
        /// 验证字符串是否为IP地址 
        /// </summary>
        /// <param name="ip"></param>
        /// <returns></returns>
        public static bool IsIPAddress(this string ip)
        {
            if (string.IsNullOrEmpty(ip) || ip.Length < 7 || ip.Length > 15) return false;

            string regformat = @"^(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])$";

            Regex regex = new Regex(regformat, RegexOptions.IgnoreCase);

            return regex.IsMatch(ip);
        }


        /// <summary>
        /// WeeksOfYear
        /// </summary>
        /// <param name="dTime"></param>
        /// <returns></returns>
        public static int WeeksOfYear(this DateTime dTime)
        {
            try
            {
                var dayOfYear = dTime.DayOfYear;
                var tempDate = new DateTime(dTime.Year, 1, 1);
                var tempDayOfWeek = (int)tempDate.DayOfWeek;
                tempDayOfWeek = tempDayOfWeek == 0 ? 7 : tempDayOfWeek;
                var index = (int)dTime.DayOfWeek;
                index = index == 0 ? 7 : index;
                DateTime retStartDay = dTime.AddDays(-(index - 1));
                DateTime retEndDay = dTime.AddDays(7 - index);
                var weekIndex = (int)Math.Ceiling(((double)dayOfYear + tempDayOfWeek - 1) / 7);
                if (retStartDay.Year < retEndDay.Year)
                {
                    weekIndex = 1;
                }

                return weekIndex;
            }
            catch (Exception ex)
            {
                throw new Exception(ex.Message);
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="targe"></param>
        /// <param name="size"></param>
        /// <returns></returns>
        public static List<List<T>> CreateRangeList<T>(this List<T> targe, int size)
        {
            List<List<T>> listArr = new List<List<T>>();
            //获取被拆分的数组个数  
            int arrSize = targe.Count % size == 0 ? targe.Count / size : targe.Count / size + 1;
            for (int i = 0; i < arrSize; i++)
            {
                List<T> sub = new List<T>();
                //把指定索引数据放入到list中  
                for (int j = i * size; j <= size * (i + 1) - 1; j++)
                {
                    if (j <= targe.Count - 1)
                    {
                        sub.Add(targe[j]);
                    }
                }
                listArr.Add(sub);
            }
            return listArr;
        }

        /// <summary>
        /// 32位MD5加密
        /// </summary>
        /// <param name="password"></param>
        /// <returns></returns>
        public static string MD5Encrypt32(this string password)
        {
            var inputBytes = Encoding.UTF8.GetBytes(password);
            var hashBytes = MD5.HashData(inputBytes);
            return Convert.ToHexString(hashBytes);
        }

        /// <summary>
        /// 16位MD5加密
        /// </summary>
        /// <param name="password"></param>
        /// <returns></returns>
        public static string MD5Encrypt16(this string password)
        {
            var md5 = MD5.Create(); //new MD5CryptoServiceProvider();
            string t2 = BitConverter.ToString(md5.ComputeHash(Encoding.Default.GetBytes(password)), 4, 8);
            t2 = t2.Replace("-", "");
            return t2;
        }

        /// <summary>
        /// 64位MD5加密
        /// </summary>
        /// <param name="password"></param>
        /// <returns></returns>
        public static string MD5Encrypt64(this string password)
        {
            string cl = password;
            //string pwd = "";
            MD5 md5 = MD5.Create(); //实例化一个md5对像
                                    // 加密后是一个字节类型的数组，这里要注意编码UTF8/Unicode等的选择　
            byte[] s = md5.ComputeHash(Encoding.UTF8.GetBytes(cl));
            return Convert.ToBase64String(s);
        }

        #region Base64加码解码
        /// <summary>
        /// Base64编码，采用utf8编码
        /// </summary>
        /// <param name="strPath">待编码的明文</param>
        /// <returns>Base64编码后的字符串</returns>
        public static string Base64Encrypt(this string strPath)
        {
            string returnData;
            Encoding encode = Encoding.UTF8;
            byte[] bytedata = encode.GetBytes(strPath);
            try
            {
                returnData = Convert.ToBase64String(bytedata, 0, bytedata.Length);
            }
            catch
            {
                returnData = strPath;
            }
            return returnData;
        }

        /// <summary>
        /// Base64解码，采用utf8编码方式解码
        /// </summary>
        /// <param name="strPath">待解码的密文</param>
        /// <returns>Base64解码的明文字符串</returns>
        public static string Base64DesEncrypt(this string strPath)
        {
            string returnData;
            byte[] bpath = Convert.FromBase64String(strPath);
            try
            {
                returnData = Encoding.UTF8.GetString(bpath);
            }
            catch
            {
                returnData = strPath;
            }
            return returnData;
        }
        #endregion

        /// <summary>
        /// SHA1 加密 
        /// </summary>
        /// <param name="content">需要加密字符串</param>
        /// <param name="encode">指定加密编码</param>
        /// <param name="upperOrLower">大小写格式（大写：X2;小写:x2）默认小写</param> 
        public static string SHA1Encrypt(this string content, Encoding encode, string upperOrLower = "x2")
        {
            try
            {
                var buffer = encode.GetBytes(content);//用指定编码转为bytes数组
                var data = SHA1.Create().ComputeHash(buffer);
                var sb = new StringBuilder();
                foreach (var t in data)
                {
                    sb.Append(t.ToString(upperOrLower));
                }

                return sb.ToString();
            }
            catch (Exception ex)
            {
                return "SHA1加密出错：" + ex.Message;
            }
        }

        /// <summary>
        /// SHA256加密
        /// </summary>
        /// <param name="strIN">要加密的string字符串</param>
        /// <returns>SHA256加密之后的密文</returns>
        public static string SHA256Encrypt(this string strIN)
        {
            byte[] tmpByte;
            SHA256 sha256 = SHA256.Create();// new SHA256Managed();
            tmpByte = sha256.ComputeHash(GetKeyByteArray(strIN));

            StringBuilder rst = new StringBuilder();
            for (int i = 0; i < tmpByte.Length; i++)
            {
                rst.Append(tmpByte[i].ToString("x2"));
            }
            sha256.Clear();
            return rst.ToString();
        }

        /// <summary>
        /// 获取要加密的string字符串字节数组
        /// </summary>
        /// <param name="strKey">待加密字符串</param>
        /// <returns>加密数组</returns>
        private static byte[] GetKeyByteArray(this string strKey)
        {
            UTF8Encoding Asc = new UTF8Encoding();
            int tmpStrLen = strKey.Length;
            byte[] tmpByte = new byte[tmpStrLen - 1];
            tmpByte = Asc.GetBytes(strKey);
            return tmpByte;
        }


        /// <summary>
        /// 转换成十六进制字符串
        /// </summary>
        /// <param name="byteDatas"></param>
        /// <returns></returns>
        public static string ToHexString(this byte[] byteDatas)
        {
            StringBuilder builder = new StringBuilder();
            for (int i = 0; i < byteDatas.Length; i++)
            {
                builder.Append(string.Format("{0:X2} ", byteDatas[i]));
            }
            return builder.ToString().Trim();
        }

    }
}